package system.track;

import system.train.Train;
import java.util.LinkedList;
import system.communication.ConcreteMonitor;

/**
 * A Sensor for generic use, implementing the Sensor interface.  This 
 * represents one of the physical sensors on the train track that a train
 * can trigger as it passes over, alerting the program to its location.
 * 
 * @author David
 * @version Cycle 1 - complete
 */
public class GenericSensor implements Sensor
{
    private int id;
    // multiple trains are accounted for, for cycle 2:
    private LinkedList<Train> trains;

    /**
     * Constructor for Objects of class GenericSensor.  Instantiates
     * the trains that can trigger the sensor.
     */
    public GenericSensor()
    {
        trains = new LinkedList<Train>();
    }

    /**
     * Registers an integer ID with the the sensor and passes that to
     * the ConcreteMonitor.
     *  
     * @param id the ID number of the sensor from the track map
     */
    public void setID(int id)
    {
        this.id = id;
        ConcreteMonitor.getInstance().registerSensor(this);
    }

    /**
     * Retrieves the ID number of the sensor.
     * 
     * @return an ID number that matches the number of a sensor on the map.
     */
    public int getID()
    {
        return id;
    }

    /**
     * This registers a train to recieve notification calls when the sensor
     * is tripped.  Synchronized for threading.
     *
     * @param t a reference to the train object to register.
     */
    public synchronized void registerForNotification(Train t)
    {
        System.out.println("Sensor " + this.id + " has been registered");
        trains.add(t);
    }

    /**
     * This removes a train from the sensors internal data structure of trains
     * to notify when it is tripped.  Synchronized for threading.
     * 
     * @param t a reference to the train to remove from notification.
     */
    public synchronized void unregisterForNotification(Train t)
    {
        System.out.println("Sensor " + this.id + " has been unregistered");
        trains.remove(t);
    }

    /**
     * This function is called when a sensor is tripped.  The major effect
     * of this is that the sensor will notify any trains registered to it.
     * Synchronized for threading.
     */
    public synchronized void tripped()
    {
        System.out.println("Sensor " + this.id + " has been tripped");
        for (Train aTrain : trains)
        {
            aTrain.tripSensor();
        }
    }
}